/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package utn.tsb.tej.world_logic;

import java.util.Arrays;

/**
 * this class receives an attacker and a defender country. After call the
 * resolve() method the atributes will be:
 * ||attackerCountry: the attacker country
 * ||defenderCountry: the defender contry
 * ||attackerCountryArmiesRemain: amount of armies that should be assigned tho
 *                              the attacker comntry
 * ||defenderCountryArmiesRemain: amount of armies that should be assigned tho
 *                              the defender comntry
 * ||attackerPlayer: the player that declares the attack
 * ||defenderPlayer: the player that receives the attack
 * ||conquered: true if the attacker wins the attack. The defender country must
 *              be transfered to the attacker
 * @author Gaston M. Quiroga <gaston.mauricio.quiroga@gmail.com>
 */
public class Attack implements Comparable {

    private Country attackerCountry = null;
    private Country defenderCountry = null;
    private int attackerCountryArmiesRemain;
    private int defenderCountryArmiesRemain;
    private Player attackerPlayer;
    private Player defenderPlayer;
    private boolean conquered = false;
    private boolean resolved = false;
    private int order;
    private static int orderCount = 0;
    int attackerDicesAmount;
    public int[] atkRolls;
    public int[] defRolls;

    public Attack(Country attackerCountry, Country defenderCountry, int amount) {
        this.attackerCountry = attackerCountry;
        this.defenderCountry = defenderCountry;
        attackerCountryArmiesRemain = attackerCountry.getArmies();
        defenderCountryArmiesRemain = defenderCountry.getArmies();
        attackerPlayer = attackerCountry.getOwner();
        defenderPlayer = defenderCountry.getOwner();
        orderCount++;
        order = orderCount;
        this.attackerDicesAmount = amount;
    }

    public Attack() {
        orderCount++;
        order = orderCount;
    }

    public int getAttackerCountryArmiesRemain() {
        return attackerCountryArmiesRemain;
    }

    public Player getAttackerPlayer() {
        return attackerPlayer;
    }

    public boolean isConquered() {
        return conquered;
    }

    public int getDefenderCountryArmiesRemain() {
        return defenderCountryArmiesRemain;
    }

    public Player getDefenderPlayer() {
        return defenderPlayer;
    }

    public int getOrder() {
        return order;
    }

    public Country getAttackerCountry() {
        return attackerCountry;
    }

    public void setAttackerCountry(Country attackerCountry) {
        this.attackerCountry = attackerCountry;
        this.attackerCountryArmiesRemain = attackerCountry.getArmies();
        this.attackerPlayer = attackerCountry.getOwner();
    }

    public Country getDefenderCountry() {
        return defenderCountry;
    }

    public void setDefenderCountry(Country defenderCountry) {
        this.defenderCountry = defenderCountry;
        this.defenderCountryArmiesRemain = defenderCountry.getArmies();
        this.defenderPlayer = defenderCountry.getOwner();
    }

    @Override
    public int compareTo(Object o) {
        Round r = (Round) o;
        int dif = this.order - r.getOrder();
        return dif;
    }

    /**************************************************************************************/
    private int getAttackerDices() {
        Situation situation = WorldLogicFacade.world.getRounds().getLast().getSituation();
        int dicesAmount = attackerCountry.getArmies() - 1;
        if (dicesAmount > 3) {
            dicesAmount = 3;
        }
        if (defenderCountry.getArmies() >= 3 && attackerCountry.getArmies() / 2 >= defenderCountry.getArmies()) {
            dicesAmount++;
        }
        if (situation instanceof SituationExtraDice) {
            if (((SituationExtraDice) situation).isAttaker()) {
                dicesAmount = dicesAmount + ((SituationExtraDice) situation).getExtraDices();
            }
        }
        if (dicesAmount > 4) {
            dicesAmount = 4;
        }
        return dicesAmount;
    }

    public int getDefenderDices() {

        Situation situation = WorldLogicFacade.world.getRounds().getLast().getSituation();
        int dicesAmount = defenderCountry.getArmies();
        if (dicesAmount > 3) {
            dicesAmount = 3;
        }
        if (situation instanceof SituationExtraDice) {
            if (!((SituationExtraDice) situation).isAttaker()) {
                dicesAmount = dicesAmount + ((SituationExtraDice) situation).getExtraDices();
            }
        }
        if (dicesAmount > 4) {
            dicesAmount = 4;
        }
        return dicesAmount;
    }

    /**
     * checks if the countries have been set.
     * @return
     */
    public boolean isSet() {
        return (attackerCountry != null && defenderCountry != null);
    }

    /**
     * sets an int[] with random numbers from 1 to 6
     * @param rolls
     */
    private void setRolls(int[] rolls) {
        for (int i = 0; i < rolls.length; i++) {
            rolls[i] = (int) (Math.random() * 6) + 1;
        }
    }

    /**
     * This method resolves the attak.
     * @param atkRolls
     * @param defRolls
     */
    public void resolve() throws Exception {
        if (resolved) {
            throw new Exception("This attack is already resolved. Cannot perform this action again");
        }
        int defenderI = getDefenderDices();
        int attackerI = attackerDicesAmount;
        atkRolls = new int[attackerI];
        defRolls = new int[defenderI];
        setRolls(defRolls);
        setRolls(atkRolls);
        sort(atkRolls);
        sort(defRolls);
        if(WorldLogicFacade.world.getRounds().getLast().getSituation() instanceof SituationExtraDice){
            SituationExtraDice situation=(SituationExtraDice)(WorldLogicFacade.world.getRounds().getLast().getSituation());
            if(situation.isAttaker()){
                attackerI=attackerI-situation.getExtraDices();
            }else{
                defenderI=defenderI-situation.getExtraDices();
            }
        }

        int amnt = attackerI < defenderI ? attackerI : defenderI;
        for (int i = 0; i < amnt; i++) {
            if (atkRolls[i] > defRolls[i]) {
                defenderCountryArmiesRemain--;
            } else {
                attackerCountryArmiesRemain--;
            }
            if (defenderCountryArmiesRemain == 0) {//el atacante nunca podria quedarse sin ejercitos por que siempre tira con mas dados que ejercitos
                conquered = true;
                attackerPlayer.setConquered(true);
                break;
            }
        }
        resolved = true;
    }

    /**
     * 
     * @return
     */
    public boolean isValid() throws Exception {
        boolean valid = true;
        if (attackerPlayer == defenderPlayer) {
            valid = false;
            throw new Exception("Atacante y defensor son el mismo Jugador");
        }
        if (attackerCountry.getAttackableCountries().indexOf(defenderCountry) == -1) {
            valid = false;
            throw new Exception("El pais atacado no esta dentro de los paises que el atacante puede atacar");
        }
        if (attackerDicesAmount > getAttackerDices()) {
            valid = false;
            throw new Exception("El atacante intenta usar mas dados de los adecuadosl");
        }
        return valid;
    }

    public void sort(int[] ar) {
        Arrays.sort(ar);
        int l = ar.length;
        int[] aux = new int[l];
        for (int i = 0; i < l; i++) {
            aux[i] = ar[l - 1 - i];
        }
        for (int i = 0; i < l; i++) {
            ar[i] = aux[i];
        }
    }
}
